package com.saas.datasource.core;

import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.saas.datasource.core.druid.DruidDataSourceConfig;
import com.saas.datasource.core.hikari.HikariCpConfig;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 数据源相关配置
 */
@Configuration
public class DataSourceBase {
	@Autowired
	private PaginationInterceptor paginationInterceptor;
	@Bean(name = "dataSourceMaster")
	@Primary // 当有多个实现类型时，优先使用
	public DataSource dataSourceMaster(DataSourceConfig dataSourceConfig) throws Exception {
		if("druid".equals(dataSourceConfig.getConfigType())){
			DruidDataSourceConfig saas=dataSourceConfig.getDsaas();
			DruidDataSource druidDataSourceMaster = new DruidDataSource();
			druidDataSourceMaster.setUrl(saas.getUrl());
			druidDataSourceMaster.setUsername(saas.getUsername());
			druidDataSourceMaster.setPassword(saas.getPassword());
			druidDataSourceMaster.setDriverClassName(saas.getDriverClassName());
			druidDataSourceMaster.setInitialSize( saas.getInitialSize());
			druidDataSourceMaster.setMaxActive( saas.getMaxActive());
			druidDataSourceMaster.setMinIdle(saas.getMinIdle());
			druidDataSourceMaster.setMaxWait(saas.getMaxWait());
			return druidDataSourceMaster;
		}else if("hikari".equals(dataSourceConfig.getConfigType())){
			HikariCpConfig config =dataSourceConfig.getHsaas();
			if (config == null) {
				return null;
			}
			int minConns = config.getMinConn();
			if (minConns < 1) {
				minConns = 1;
				config.setMinConn(minConns);
			}
			int maxConns = config.getMaxConn();
			if (maxConns < 1) {
				maxConns = 1;
				config.setMaxConn(maxConns);
			}
			int connIdleTimeout = config.getConnIdleTimeout() * 1000;
			if (connIdleTimeout < 60000) {
				// 最小一分钟
				connIdleTimeout = 60000;
				config.setConnIdleTimeout(60);
			}
			int connBusyTimeout = config.getConnBusyTimeout() * 1000;
			if (connBusyTimeout < 30000) {
				// 最小30秒钟
				connBusyTimeout = 30000;
				config.setConnBusyTimeout(30);
			}
			int connMaxAge = config.getConnMaxAge() * 1000;
			if (connMaxAge < 600000) {
				// 最小60分钟
				connMaxAge = 600000;
				config.setConnMaxAge(60);
			}
			// HikariConfig
			HikariConfig hikariConfig = new HikariConfig();
			hikariConfig.setPoolName("master");
			// 数据库驱动
			hikariConfig.setDriverClassName(config.getDriverClassName());
			// 服务器连接字符串
			hikariConfig.setJdbcUrl(config.getUrl());
			// 登陆用户名
			hikariConfig.setUsername(config.getUsername());
			// 登陆密码
			hikariConfig.setPassword(config.getPassword());
			// 测试sql hikari不配置testSql,会直接使用Connection.isValid()检活
			if (!hikariConfig.getDriverClassName().contains("mysql")) {
				hikariConfig.setConnectionTestQuery(config.getTestSql());
			}
			// 最小空闲连接数
			hikariConfig.setMinimumIdle(minConns);
			// 最大连接数
			hikariConfig.setMaximumPoolSize(maxConns);
			// 空闲超时(秒钟)
			hikariConfig.setIdleTimeout(connIdleTimeout);
			// 连接超时(秒钟)
			hikariConfig.setConnectionTimeout(connBusyTimeout);
			// 连接寿命(秒钟)
			hikariConfig.setMaxLifetime(connMaxAge);
			// 数据库方言
			HikariDataSource hikariDataSource = new HikariDataSource(hikariConfig);
			return hikariDataSource;
		}
		return null;
	}
	/**
	 * 动态数据源，配置需要使用到的多个数据源
	 * @param master
	 * @return
	 */
	@Bean(name = "dynamicDataSourceMaster")
	public DynamicDataSource dynamicDataSource(@Qualifier("dataSourceMaster") DataSource master) {
		DynamicDataSource dynamicDataSource = new DynamicDataSource();
		dynamicDataSource.myMap = new ConcurrentHashMap<>();//保存我们有的数据源，方便后面动态增加
		dynamicDataSource.myMap.put("master", master);
		dynamicDataSource.setDefaultTargetDataSource(master);
		dynamicDataSource.setTargetDataSources(dynamicDataSource.myMap);
		return dynamicDataSource;
	}

	@Bean
	public PlatformTransactionManager transactionManager(DynamicDataSource dynamicDataSource) {
		return new DataSourceTransactionManager(dynamicDataSource);
	}

	@Bean
	public SqlSessionFactory sqlSessionFactory(DynamicDataSource dynamicDataSource) throws Exception {
		MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
		sessionFactory.setDataSource(dynamicDataSource);
		//		关键代码 设置 MyBatis-Plus 分页插件
		Interceptor[] plugins = {paginationInterceptor};
		sessionFactory.setPlugins(plugins);
		sessionFactory.setMapperLocations(((ResourcePatternResolver) new PathMatchingResourcePatternResolver())
				.getResources("classpath*:/mapper/**/*Mapper.xml"));
		return sessionFactory.getObject();
	}

}